home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / emulator / bsvc-1.000 / bsvc-1 / bsvc-1.0.4 / src / Assemblers / 68kasm / build.c < prev    next >
C/C++ Source or Header  |  1995-07-26  |  18KB  |  816 lines

  1. /******************************************************************************
  2.  * $Id: build.c,v 1.2 1994/09/22 00:04:01 bmott Exp $
  3.  ******************************************************************************
  4.  *
  5.  *        BUILD.C
  6.  *        Instruction Building Routines for 68000 Assembler
  7.  *
  8.  * Description: The functions in this file build instructions, that is,
  9.  *        they assemble the instruction word and its extension
  10.  *        words given the skeleton bit mask for the instruction
  11.  *        and opDescriptors for its operand(s). The instructions
  12.  *        that each routine builds are noted above it in a
  13.  *        comment. All the functions share the same calling
  14.  *        sequence (except zeroOp, which has no argument and
  15.  *        hence omits the operand descriptors), which is as
  16.  *        follows: 
  17.  *
  18.  *            general_name(mask, size, source, dest, errorPtr);
  19.  *            int mask, size;
  20.  *            opDescriptor *source, *dest;
  21.  *            int *errorPtr;
  22.  *
  23.  *        except
  24.  *        
  25.  *            zeroOp(mask, size, errorPtr);
  26.  *            int mask, size, *errorPtr;
  27.  *
  28.  *        The mask argument is the skeleton mask for the 
  29.  *        instruction, i.e., the instruction word before the 
  30.  *        addressing information has been filled in. The size 
  31.  *        argument contains the size code that was specified with 
  32.  *        the instruction (using the definitions in ASM.H) or 0 
  33.  *        if no size code was specified. Arguments source and 
  34.  *        dest are pointers to opDescriptors for the two 
  35.  *        operands (only source is valid in some cases). The last 
  36.  *        argument is used to return a status via the standard 
  37.  *        mechanism.
  38.  *
  39.  *      Author: Paul McKee
  40.  *        ECE492    North Carolina State University
  41.  *
  42.  *        Date:    12/13/86
  43.  *
  44.  *   Copyright 1990-1991 North Carolina State University. All Rights Reserved.
  45.  *
  46.  ******************************************************************************
  47.  * $Log: build.c,v $
  48.  * Revision 1.2  1994/09/22  00:04:01  bmott
  49.  * Changed short disp to int disp in dbcc
  50.  *
  51.  * Revision 1.1  1994/08/29  23:54:44  bmott
  52.  * Initial revision
  53.  *
  54.  *****************************************************************************/
  55.  
  56. #include <stdio.h>
  57. #include "asm.h"
  58.  
  59. extern int loc;
  60. extern char pass2;
  61.  
  62.  
  63. /***********************************************************************
  64.  *
  65.  *    Function move builds the MOVE and MOVEA instructions
  66.  *
  67.  ***********************************************************************/
  68.  
  69. move(mask, size, source, dest, errorPtr)
  70. int mask, size;
  71. opDescriptor *source, *dest;
  72. int *errorPtr;
  73. {
  74. unsigned short moveMask;
  75. char destCode;
  76.  
  77.     /* Check whether the instruction can be assembled as MOVEQ */
  78.     if (source->mode == Immediate && source->backRef
  79.         && size == LONG && dest->mode == DnDirect
  80.         && source->data >= -128 && source->data <= 127) {
  81.         moveq(0x7000, size, source, dest, errorPtr);
  82.         return;
  83.         }
  84.  
  85.     /* Otherwise assemble it as plain MOVE */
  86.     moveMask = mask | effAddr(source);
  87.     destCode = effAddr(dest);
  88.     moveMask |= (destCode & 0x38) << 3 | (destCode & 7) << 9;
  89.     if (pass2)
  90.         output(moveMask, WORD);
  91.     loc += 2;
  92.     extWords(source, size, errorPtr);
  93.     extWords(dest, size, errorPtr);
  94. }
  95.  
  96.  
  97. /***********************************************************************
  98.  *
  99.  *    Function zeroOp builds the following instructions:
  100.  *     ILLEGAL
  101.  *     NOP
  102.  *     RESET
  103.  *     RTE
  104.  *     RTR
  105.  *     RTS
  106.  *     TRAPV
  107.  *
  108.  ***********************************************************************/
  109.  
  110. zeroOp(mask, size, errorPtr)
  111. int mask, size;
  112. int *errorPtr;
  113. {
  114.     if (pass2)
  115.         output(mask, WORD);
  116.     loc += 2;
  117. }
  118.  
  119.  
  120. /***********************************************************************
  121.  *
  122.  *    Function oneOp builds the following instructions:
  123.  *     ASd  <ea>
  124.  *     CLR 
  125.  *     JMP
  126.  *     JSR
  127.  *     LSd  <ea>
  128.  *     MOVE <ea>,CCR
  129.  *     MOVE <ea>,SR
  130.  *     NBCD
  131.  *     NEG
  132.  *     NEGX
  133.  *     NOT
  134.  *     PEA
  135.  *     ROd  <ea>
  136.  *     ROXd <ea>
  137.  *     TAS
  138.  *     TST
  139.  *
  140.  ***********************************************************************/
  141.  
  142. oneOp(mask, size, source, dest, errorPtr)
  143. int mask, size;
  144. opDescriptor *source, *dest;
  145. int *errorPtr;
  146. {
  147.     if (pass2)
  148.         output(mask | effAddr(source), WORD);
  149.     loc += 2;
  150.     extWords(source, size, errorPtr);
  151. }
  152.  
  153.  
  154. /***********************************************************************
  155.  *
  156.  *    Function arithReg builds the following instructions:
  157.  *     ADD <ea>,Dn
  158.  *     ADDA
  159.  *     AND <ea>,Dn
  160.  *     CHK
  161.  *     CMP
  162.  *     CMPA
  163.  *     DIVS
  164.  *     DIVU
  165.  *     LEA
  166.  *     MULS
  167.  *     MULU
  168.  *     OR <ea>,Dn
  169.  *     SUB <ea>,Dn
  170.  *     SUBA
  171.  *
  172.  ***********************************************************************/
  173.  
  174. arithReg(mask, size, source, dest, errorPtr)
  175. int mask, size;
  176. opDescriptor *source, *dest;
  177. int *errorPtr;
  178. {
  179.     if (pass2)
  180.         output(mask | effAddr(source) | (dest->reg << 9), WORD);
  181.     loc += 2;
  182.     extWords(source, size, errorPtr);
  183. }
  184.  
  185.  
  186. /***********************************************************************
  187.  *
  188.  *    Function arithAddr builds the following instructions:
  189.  *     ADD Dn,<ea>
  190.  *     AND Dn,<ea>
  191.  *     BCHG Dn,<ea>
  192.  *     BCLR Dn,<ea>
  193.  *     BSET Dn,<ea>
  194.  *     BTST Dn,<ea>
  195.  *     EOR
  196.  *     OR Dn,<ea>
  197.  *     SUB Dn,<ea>
  198.  *
  199.  ***********************************************************************/
  200.  
  201.  
  202. arithAddr(mask, size, source, dest, errorPtr)
  203. int mask, size;
  204. opDescriptor *source, *dest;
  205. int *errorPtr;
  206. {
  207.     if (pass2)
  208.         output(mask | effAddr(dest) | (source->reg << 9), WORD);
  209.     loc += 2;
  210.     extWords(dest, size, errorPtr);
  211. }
  212.  
  213.  
  214. /***********************************************************************
  215.  *
  216.  *    Function immedInst builds the following instructions:
  217.  *     ADDI
  218.  *     ANDI
  219.  *     CMPI
  220.  *     EORI
  221.  *     ORI
  222.  *     SUBI
  223.  *
  224.  ***********************************************************************/
  225.  
  226.  
  227. immedInst(mask, size, source, dest, errorPtr)
  228. int mask, size;
  229. opDescriptor *source, *dest;
  230. int *errorPtr;
  231. {
  232. unsigned short type;
  233.  
  234.     /* Check whether the instruction is an immediate ADD or SUB 
  235.            that can be assembled as ADDQ or SUBQ */
  236.     /* Check the mask to determine the operation */
  237.     type = mask & 0xFF00;
  238.     if ((type == 0x0600 || type == 0x0400)
  239.         && source->backRef && source->data >= 1 && source->data <= 8)
  240.             if (type == 0x0600) {
  241.                 /* Assemble as ADDQ */
  242.                 quickMath(0x5000 | (mask & 0x00C0), size,
  243.                       source, dest, errorPtr);
  244.                 return;
  245.                 }
  246.             else {
  247.                 /* Assemble as SUBQ */
  248.                 quickMath(0x5100 | (mask & 0x00C0), size,
  249.                       source, dest, errorPtr);
  250.                 return;
  251.                 }
  252.  
  253.     /* Otherwise assemble as an ordinary instruction */
  254.     if (pass2)
  255.         output(mask | effAddr(dest), WORD);
  256.     loc += 2;
  257.     extWords(source, size, errorPtr);
  258.     extWords(dest, size, errorPtr);
  259. }
  260.  
  261.  
  262. /***********************************************************************
  263.  *
  264.  *    Function quickMath builds the following instructions:
  265.  *     ADDQ
  266.  *     SUBQ
  267.  *
  268.  ***********************************************************************/
  269.  
  270.  
  271. quickMath(mask, size, source, dest, errorPtr)
  272. int mask, size;
  273. opDescriptor *source, *dest;
  274. int *errorPtr;
  275. {
  276. int status;
  277.  
  278.     if (pass2) {
  279.         output(mask | effAddr(dest) | ((source->data & 7) << 9), WORD);
  280.         if (source->data < 1 || source->data > 8)
  281.             NEWERROR(*errorPtr, INV_QUICK_CONST);
  282.         }
  283.     loc += 2;
  284.     extWords(dest, size, errorPtr);
  285. }
  286.  
  287.  
  288. /***********************************************************************
  289.  *
  290.  *    Function movep builds the MOVEP instruction.
  291.  *
  292.  ***********************************************************************/
  293.  
  294.  
  295. movep(mask, size, source, dest, errorPtr)
  296. int mask, size;
  297. opDescriptor *source, *dest;
  298. int *errorPtr;
  299. {
  300.     if (pass2)
  301.         if (source->mode == DnDirect) {
  302.             /* Convert plain address register indirect to address
  303.                register indirect with displacement of 0 */
  304.             if (dest->mode == AnInd) {
  305.                 dest->mode = AnIndDisp;
  306.                 dest->data = 0;
  307.                 }
  308.             output(mask | (source->reg << 9) | (dest->reg), WORD);
  309.             loc += 2;
  310.             extWords(dest, size, errorPtr);
  311.             }
  312.         else {
  313.             /* Convert plain address register indirect to address
  314.                register indirect with displacement of 0 */
  315.             if (source->mode == AnInd) {
  316.                 source->mode = AnIndDisp;
  317.                 source->data = 0;
  318.                 }
  319.             output(mask | (dest->reg << 9) | (source->reg), WORD);
  320.             loc += 2;
  321.             extWords(source, size, errorPtr);
  322.             }
  323.     else
  324.         loc += 4;
  325. }
  326.  
  327.  
  328. /***********************************************************************
  329.  *
  330.  *    Function moves builds the MOVES instruction.
  331.  *
  332.  ***********************************************************************/
  333.  
  334.  
  335. moves(mask, size, source, dest, errorPtr)
  336. int mask, size;
  337. opDescriptor *source, *dest;
  338. int *errorPtr;
  339. {
  340.     if (pass2)
  341.         if (source->mode & (DnDirect | AnDirect)) {
  342.             output(mask | effAddr(dest), WORD);
  343.             loc += 2;
  344.             if (source->mode == DnDirect)
  345.                 output(0x0800 | (source->reg << 12), WORD);
  346.             else
  347.                 output(0x8800 | (source->reg << 12), WORD);
  348.             loc += 2;
  349.             }
  350.         else {
  351.             output(mask | effAddr(source), WORD);
  352.             loc += 2;
  353.             if (dest->mode == DnDirect)
  354.                 output(dest->reg << 12, WORD);
  355.             else
  356.                 output(0x8000 | (dest->reg << 12), WORD);
  357.             loc += 2;
  358.             }
  359.     else
  360.         loc += 4;
  361.     extWords((source->mode & (DnDirect | AnDirect)) ? dest : source,
  362.          size, errorPtr);
  363. }
  364.  
  365.  
  366. /***********************************************************************
  367.  *
  368.  *    Function moveReg builds the following instructions:
  369.  *     MOVE from CCR
  370.  *     MOVE from SR
  371.  *
  372.  ***********************************************************************/
  373.  
  374.  
  375. moveReg(mask, size, source, dest, errorPtr)
  376. int mask, size;
  377. opDescriptor *source, *dest;
  378. int *errorPtr;
  379. {
  380.     if (pass2)
  381.         output(mask | effAddr(dest), WORD);
  382.     loc += 2;
  383.     extWords(dest, size, errorPtr);
  384. }
  385.  
  386.  
  387. /***********************************************************************
  388.  *
  389.  *    Function staticBit builds the following instructions:
  390.  *     BCHG #n,<ea>
  391.  *     BCLR #n,<ea>
  392.  *     BSET #n,<ea>
  393.  *     BTST #n,<ea>
  394.  *
  395.  ***********************************************************************/
  396.  
  397.  
  398. staticBit(mask, size, source, dest, errorPtr)
  399. int mask, size;
  400. opDescriptor *source, *dest;
  401. int *errorPtr;
  402. {
  403.     if (pass2) {
  404.         output(mask | effAddr(dest), WORD);
  405.         loc += 2;
  406.         output(source->data & 0xFF, WORD);
  407.         loc += 2;
  408.         }
  409.     else
  410.         loc += 4;
  411.     extWords(dest, size, errorPtr);
  412. }
  413.  
  414.  
  415. /***********************************************************************
  416.  *
  417.  *    Function movec builds the MOVEC instruction.
  418.  *
  419.  ***********************************************************************/
  420.  
  421.  
  422. movec(mask, size, source, dest, errorPtr)
  423. int mask, size;
  424. opDescriptor *source, *dest;
  425. int *errorPtr;
  426. {
  427. unsigned short mask2;
  428. opDescriptor *regOp;
  429. int controlMode;
  430.  
  431.     if (pass2) {
  432.         output(mask, WORD);
  433.         loc += 2;
  434.         if (mask & 1) {
  435.             regOp = source;
  436.             controlMode = dest->mode;
  437.             }
  438.         else {
  439.             regOp = dest;
  440.             controlMode = source->mode;
  441.             }
  442.         mask2 = regOp->reg << 12;
  443.         if (regOp->mode == AnDirect)
  444.             mask2 |= 0x8000;
  445.         switch (controlMode) {
  446.             case SFCDirect : mask2 |= 0x000; break;
  447.             case DFCDirect : mask2 |= 0x001; break;
  448.             case USPDirect : mask2 |= 0x800; break;
  449.             case VBRDirect : mask2 |= 0x801; break;
  450.             }
  451.         output(mask2, WORD);
  452.         loc += 2;
  453.         }
  454.     else
  455.         loc += 4;
  456. }
  457.  
  458.  
  459. /***********************************************************************
  460.  *
  461.  *    Function trap builds the TRAP instruction.
  462.  *
  463.  ***********************************************************************/
  464.  
  465.  
  466. trap(mask, size, source, dest, errorPtr)
  467. int mask, size;
  468. opDescriptor *source, *dest;
  469. int *errorPtr;
  470. {
  471.     if (pass2) {
  472.         output(mask | (source->data & 0xF), WORD);
  473.         if (source->data < 0 || source->data > 15)
  474.             NEWERROR(*errorPtr, INV_VECTOR_NUM);
  475.         }
  476.     loc += 2;
  477. }
  478.  
  479.  
  480. /***********************************************************************
  481.  *
  482.  *    Function branch builds the following instructions:
  483.  *     BCC (BHS)   BGT     BLT         BRA
  484.  *     BCS (BLO)   BHI     BMI         BSR
  485.  *     BEQ         BLE     BNE         BVC
  486.  *     BGE         BLS     BPL         BVS
  487.  *
  488.  ***********************************************************************/
  489.  
  490.  
  491. branch(mask, size, source, dest, errorPtr)
  492. int mask, size;
  493. opDescriptor *source, *dest;
  494. int *errorPtr;
  495. {
  496. char shortDisp;
  497. int disp;
  498.  
  499.     disp = source->data - loc - 2;
  500.     shortDisp = FALSE;
  501.     if (size == SHORT || (size != LONG && source->backRef 
  502.         && disp >= -128 && disp <= 127 && disp))
  503.         shortDisp = TRUE;
  504.     if (pass2) {
  505.         if (shortDisp) {
  506.             output(mask | (disp & 0xFF), WORD);
  507.             loc += 2;
  508.             if (disp < -128 || disp > 127 || !disp)
  509.                 NEWERROR(*errorPtr, INV_BRANCH_DISP);
  510.             }
  511.         else {
  512.             output(mask, WORD);
  513.             loc += 2;
  514.             output(disp, WORD);
  515.             loc += 2;
  516.             if (disp < -32768 || disp > 32767)
  517.                 NEWERROR(*errorPtr, INV_BRANCH_DISP);
  518.             }
  519.         }
  520.     else
  521.         loc += (shortDisp) ? 2 : 4;
  522. }
  523.  
  524.  
  525. /***********************************************************************
  526.  *
  527.  *    Function moveq builds the MOVEQ instruction.
  528.  *
  529.  ***********************************************************************/
  530.  
  531.  
  532. moveq(mask, size, source, dest, errorPtr)
  533. int mask, size;
  534. opDescriptor *source, *dest;
  535. int *errorPtr;
  536. {
  537.     if (pass2) {
  538.         output(mask | (dest->reg << 9) | (source->data & 0xFF), WORD);
  539.         if (source->data < -128 || source->data > 127)
  540.             NEWERROR(*errorPtr, INV_QUICK_CONST);
  541.         }
  542.     loc += 2;
  543. }
  544.  
  545.  
  546. /***********************************************************************
  547.  *
  548.  *    Function immedToCCR builds the following instructions:
  549.  *     ANDI to CCR
  550.  *     EORI to CCR
  551.  *     ORI to CCR
  552.  *
  553.  ***********************************************************************/
  554.  
  555.  
  556. immedToCCR(mask, size, source, dest, errorPtr)
  557. int mask, size;
  558. opDescriptor *source, *dest;
  559. int *errorPtr;
  560. {
  561.     if (pass2) {
  562.         output(mask, WORD);
  563.         loc += 2;
  564.         output(source->data & 0xFF, WORD);
  565.         loc += 2;
  566.         if ((source->data & 0xFF) != source->data)
  567.             NEWERROR(*errorPtr, INV_8_BIT_DATA);
  568.         }
  569.     else
  570.         loc += 4;
  571. }
  572.  
  573.  
  574. /***********************************************************************
  575.  *
  576.  *    Function immedWord builds the following instructions:
  577.  *     ANDI to SR
  578.  *     EORI to SR
  579.  *     ORI to SR
  580.  *     RTD
  581.  *     STOP
  582.  *
  583.  ***********************************************************************/
  584.  
  585.  
  586. immedWord(mask, size, source, dest, errorPtr)
  587. int mask, size;
  588. opDescriptor *source, *dest;
  589. int *errorPtr;
  590. {
  591.     if (pass2) {
  592.         output(mask, WORD);
  593.         loc += 2;
  594.         output(source->data & 0xFFFF, WORD);
  595.         loc += 2;
  596.         if (source->data < -32768 || source->data > 65535)
  597.             NEWERROR(*errorPtr, INV_16_BIT_DATA);
  598.         }
  599.     else
  600.         loc += 4;
  601. }
  602.  
  603.  
  604. /***********************************************************************
  605.  *
  606.  *    Function dbcc builds the following instructions:
  607.  *     DBCC (DBHS)  DBGE     DBLS         DBPL
  608.  *     DBCS (DBLO)  DBGT     DBLT         DBT
  609.  *     DBEQ          DBHI     DBMI        DBVC
  610.  *     DBF (DBRA)   DBLE     DBNE         DBVS
  611.  *
  612.  ***********************************************************************/
  613.  
  614.  
  615. dbcc(mask, size, source, dest, errorPtr)
  616. int mask, size;
  617. opDescriptor *source, *dest;
  618. int *errorPtr;
  619. {
  620.   int disp;
  621.  
  622.     disp = dest->data - loc - 2;
  623.     if (pass2) {
  624.         output(mask | source->reg, WORD);
  625.         loc += 2;
  626.         output(disp, WORD);
  627.         loc += 2;
  628.         if (disp < -32768 || disp > 32767)
  629.             NEWERROR(*errorPtr, INV_BRANCH_DISP);
  630.         }
  631.     else
  632.         loc += 4;
  633. }
  634.  
  635.  
  636. /***********************************************************************
  637.  *
  638.  *    Function scc builds the following instructions:
  639.  *     SCC (SHS)   SGE      SLS        SPL
  640.  *     SCS (SLO)   SGT      SLT        ST
  641.  *     SEQ         SHI      SMI        SVC
  642.  *     SF         SLE      SNE        SVS
  643.  *
  644.  ***********************************************************************/
  645.  
  646.  
  647. scc(mask, size, source, dest, errorPtr)
  648. int mask, size;
  649. opDescriptor *source, *dest;
  650. int *errorPtr;
  651. {
  652.     if (pass2)
  653.         output(mask | effAddr(source), WORD);
  654.     loc += 2;
  655.     extWords(source);
  656. }
  657.  
  658.  
  659. /***********************************************************************
  660.  *
  661.  *    Function shiftReg builds the following instructions:
  662.  *     ASd    Dx,Dy
  663.  *     LSd    Dx,Dy
  664.  *     ROd    Dx,Dy
  665.  *     ROXd    Dx,Dy
  666.  *     ASd    #<data>,Dy
  667.  *     LSd    #<data>,Dy
  668.  *     ROd    #<data>,Dy
  669.  *     ROXd    #<data>,Dy
  670.  *
  671.  ***********************************************************************/
  672.  
  673.  
  674. shiftReg(mask, size, source, dest, errorPtr)
  675. int mask, size;
  676. opDescriptor *source, *dest;
  677. int *errorPtr;
  678. {
  679.     if (pass2) {
  680.         mask |= dest->reg;
  681.         if (source->mode == Immediate) {
  682.             mask |= (source->data & 7) << 9;
  683.             if (source->data < 1 || source->data > 8)
  684.                 NEWERROR(*errorPtr, INV_SHIFT_COUNT);
  685.             }
  686.         else
  687.             mask |= source->reg << 9;
  688.         output(mask, WORD);
  689.         }
  690.     loc += 2;
  691. }
  692.  
  693.  
  694. /***********************************************************************
  695.  *
  696.  *    Function exg builds the EXG instruction.
  697.  *
  698.  ***********************************************************************/
  699.  
  700.  
  701. exg(mask, size, source, dest, errorPtr)
  702. int mask, size;
  703. opDescriptor *source, *dest;
  704. int *errorPtr;
  705. {
  706.     if (pass2) {
  707.         /* Are a data register and an address register being exchanged? */
  708.         if (source->mode != dest->mode)
  709.             /* If so, the address register goes in bottom three bits */
  710.             if (source->mode == AnDirect)
  711.                 mask |= source->reg | (dest->reg << 9);
  712.             else
  713.                 mask |= dest->reg | (source->reg << 9);
  714.         else
  715.             /* Otherwise it doesn't matter which way they go */
  716.             mask |= dest->reg | (source->reg << 9);
  717.         output(mask, WORD);
  718.         }
  719.     loc += 2;
  720. }
  721.  
  722.  
  723. /***********************************************************************
  724.  *
  725.  *    Function twoReg builds the following instructions:
  726.  *     ABCD
  727.  *     ADDX
  728.  *     CMPM
  729.  *     SBCD
  730.  *     SUBX
  731.  *
  732.  ***********************************************************************/
  733.  
  734.  
  735. twoReg(mask, size, source, dest, errorPtr)
  736. int mask, size;
  737. opDescriptor *source, *dest;
  738. int *errorPtr;
  739. {
  740.     if (pass2) {
  741.         output(mask | (dest->reg << 9) | source->reg, WORD);
  742.         }
  743.     loc += 2;
  744. }
  745.  
  746.  
  747. /***********************************************************************
  748.  *
  749.  *    Function oneReg builds the following instructions:
  750.  *     EXT
  751.  *     SWAP
  752.  *     UNLK
  753.  *
  754.  ***********************************************************************/
  755.  
  756.  
  757. oneReg(mask, size, source, dest, errorPtr)
  758. int mask, size;
  759. opDescriptor *source, *dest;
  760. int *errorPtr;
  761. {
  762.     if (pass2) {
  763.         output(mask | source->reg, WORD);
  764.         }
  765.     loc += 2;
  766. }
  767.  
  768.  
  769. /***********************************************************************
  770.  *
  771.  *    Function moveUSP builds the following instructions:
  772.  *     MOVE    USP,An
  773.  *     MOVE    An,USP
  774.  *
  775.  ***********************************************************************/
  776.  
  777.  
  778. moveUSP(mask, size, source, dest, errorPtr)
  779. int mask, size;
  780. opDescriptor *source, *dest;
  781. int *errorPtr;
  782. {
  783.     if (pass2) {
  784.         if (source->mode == AnDirect)
  785.             output(mask | source->reg, WORD);
  786.         else
  787.             output(mask | dest->reg, WORD);
  788.         }
  789.     loc += 2;
  790. }
  791.  
  792.  
  793. /***********************************************************************
  794.  *
  795.  *    Function link builds the LINK instruction
  796.  *
  797.  ***********************************************************************/
  798.  
  799.  
  800. link(mask, size, source, dest, errorPtr)
  801. int mask, size;
  802. opDescriptor *source, *dest;
  803. int *errorPtr;
  804. {
  805.     if (pass2) {
  806.         output(mask | source->reg, WORD);
  807.         loc += 2;
  808.         output(dest->data, WORD);
  809.         loc += 2;
  810.         if (dest->data < -32768 || dest->data > 32767)
  811.             NEWERROR(*errorPtr, INV_16_BIT_DATA);
  812.         }
  813.     else
  814.         loc += 4;
  815. }
  816.